<template>
    <div class="base-transfer-table">
        <div class="base-transfer-table-panel base-transfer-table-left">
            <div v-if="$slots['tobeSelected']">
                <slot name="tobeSelected"></slot>
            </div>
            <BaseTable
                :columns="columns as any[]"
                :data="transferData.tobeSelectedData"
                :loading="loading"
                :page-attribute="{ size: 'small', pagerCount: 5, layout: 'prev, pager, next' }"
                :show-page-info="showPageInfo"
                :show-total="false"
                v-bind="$attrs"
            >
                <template #tableHeader>
                    <div class="flex items-center justify-between">
                        <div>待选择列表 {{ transferData.tobeSelectedData.length }} 条</div>
                        <el-button
                            plain
                            style="--el-border: var(--el-border-width) dashed var(--el-border-color)"
                            @click="onAddAll"
                        >
                            添加当前数据
                        </el-button>
                    </div>
                </template>
                <template #operations="scopeData">
                    <el-button @click="onSelectData(scopeData)">添加</el-button>
                </template>
            </BaseTable>
        </div>
        <div class="base-transfer-table-panel base-transfer-table-right">
            <div v-if="$slots['selected']">
                <slot name="selected"></slot>
            </div>
            <!--:data="transferData.selectedData"-->
            <BaseTable :columns="columns as any[]" :data="selected" :loading="loading" :show-page-info="false">
                <template #tableHeader>
                    <div class="flex items-center justify-between">
                        <div>已选择：{{ transferData.selectedData.length }}</div>
                        <el-button
                            plain
                            style="--el-border: var(--el-border-width) dashed var(--el-border-color)"
                            type="danger"
                            @click="onRemoveAll"
                        >
                            全部移除
                        </el-button>
                    </div>
                </template>
                <template #operations="scopeData">
                    <el-button plain type="danger" @click="onDeselectData(scopeData)">删除</el-button>
                </template>
            </BaseTable>
        </div>
    </div>
</template>

<script lang="ts" setup>
/**
 * @ClassName BaseTransferTable
 * @Description 表格形式穿梭框
 * @Author xuyizhuo
 * @Date 2024/12/20 21:13
 * @example
 */
import { reactive, watch } from 'vue'
import { at } from 'lodash-es'

interface VueProps {
    data: any[] // 组件显示的字段属性，同原生el-tree props
    columns: any[]
    loading?: boolean // 是否加载中
    showPageInfo?: boolean
    keepSelectedData?: boolean // 是否保留已经选中的数据。当数据变化时，是否保留之前选中的数据。默认为false，即清空之前选中的数据。
    selected: any[] // 目前已经选中的数据
}

const vueProps = withDefaults(defineProps<VueProps>(), {
    loading: false,
    showPageInfo: false,
    keepSelectedData: false,
})
const emits = defineEmits(['update:selected'])

// 穿梭框的数据
const transferData = reactive<{
    tobeSelectedData: any[]
    selectedData: any[]
}>({
    tobeSelectedData: [], // 待选择的数据（左侧未选择）
    selectedData: [], // 已选择的数据（右侧）
})
const selectedDataMap = new Map<string, any>()

const filterKey = 'id'

const updateData = () => {
    const { data } = vueProps
    const tobeSelectedData = []
    for (let i = 0, len = data.length; i < len; i++) {
        const key = at(data[i], filterKey)[0] as string
        // 不存在在已经选择的数据中
        if (selectedDataMap.has(key)) {
            continue
        }
        tobeSelectedData.push(data[i])
    }
    transferData.tobeSelectedData = tobeSelectedData
}

watch(
    () => vueProps.data,
    () => {
        updateData()
    },
)

/** 添加全部数据 */
const onAddAll = () => {
    for (let i = 0, len = transferData.tobeSelectedData.length; i < len; i++) {
        transferData.selectedData.push(transferData.tobeSelectedData[i])
        selectedDataMap.set(at(transferData.tobeSelectedData[i], filterKey)[0], transferData.tobeSelectedData[i])
    }
    transferData.tobeSelectedData = []
    emits('update:selected', transferData.selectedData)
}

/** 添加全部数据 */
const onRemoveAll = () => {
    transferData.tobeSelectedData.push(...transferData.selectedData)
    transferData.selectedData = []
    selectedDataMap.clear()
    emits('update:selected', transferData.selectedData)
}

/** 选择数据 */
const onSelectData = (scopeData: any) => {
    transferData.tobeSelectedData.splice(scopeData.$index, 1)
    const selectedData = vueProps.selected
    selectedData.push(scopeData.row)
    selectedDataMap.set(at(scopeData.row, filterKey)[0], scopeData.row)
    emits('update:selected', selectedData)
}

/** 取消选择数据 */
const onDeselectData = (scopeData: any) => {
    const selectedData = vueProps.selected
    selectedData.splice(scopeData.$index, 1)
    transferData.tobeSelectedData.push(scopeData.row)
    selectedDataMap.delete(at(scopeData.row, filterKey)[0])
    emits('update:selected', selectedData)
}
</script>

<style lang="scss" scoped>
.base-transfer-table {
    display: flex;
    gap: 12px;
    width: 100%;
    // height: 100%;

    &-panel {
        height: 100%;
    }

    // 左侧带选择数据
    &-left {
        display: flex;
        flex: 3;
        flex-direction: column;
        gap: 8px;
    }

    // 右侧已选择数据
    &-right {
        flex: 2;
    }
}
</style>
